package com.csu.mall.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.csu.mall.common.Global;
import com.csu.mall.common.dto.SkuReductionTo;
import com.csu.mall.common.es.SkuEsModel;
import com.csu.mall.common.to.SkuStockTo;
import com.csu.mall.common.utils.PageUtils;
import com.csu.mall.common.utils.Query;
import com.csu.mall.common.utils.R;
import com.csu.mall.product.Dto.SpuBoundsDto;
import com.csu.mall.product.dao.AttrDao;
import com.csu.mall.product.dao.ProductAttrValueDao;
import com.csu.mall.product.dao.SpuInfoDao;
import com.csu.mall.product.dao.SpuInfoDescDao;
import com.csu.mall.product.entity.*;
import com.csu.mall.product.feign.CouponFeignService;
import com.csu.mall.product.feign.SearchFeignService;
import com.csu.mall.product.feign.WareFeignService;
import com.csu.mall.product.service.*;
import com.csu.mall.product.vo.*;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


@Service("spuInfoService")
@Slf4j
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

    @Resource
    private SpuInfoDao spuInfoDao;


    @Resource
    private AttrDao attrDao;

    @Resource
    private SpuInfoDescDao spuInfoDescDao;

    @Resource
    private Gson gson;

    @Resource
    private ProductAttrValueDao productAttrValueDao;

    @Resource
    private CouponFeignService couponFeignService;

    @Resource
    private SpuImagesService spuImagesService;

    @Resource
    private SkuInfoService skuInfoService;

    @Resource
    private SkuImagesService skuImagesService;

    @Resource
    private SkuSaleAttrValueService skuSaleAttrValueService;

    @Resource
    private BrandService brandService;

    @Resource
    private CategoryService categoryService;

    @Resource
    private ProductAttrValueService productAttrValueService;

    @Resource
    private WareFeignService wareFeignService;

    @Resource
    private SearchFeignService searchFeignService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        QueryWrapper<SpuInfoEntity> wrapper = new QueryWrapper<>();
        String key = (String) params.get("key");

        if(StringUtils.isNotEmpty(key)){
            wrapper.eq("id", key).or().like("spu_name", key);
        }
        if(StringUtils.isNotEmpty((String)params.get("catelogId"))){
            Long catelogId = Long.parseLong( (String)params.get("catelogId"));
            if(catelogId > 0){
                wrapper.and(item->item.eq("catalog_id", catelogId));
            }
        }
        if(StringUtils.isNotEmpty((String)params.get("brandId"))){
            Long brandId =  Long.parseLong((String) params.get("brandId"));
            if(brandId > 0){
                wrapper.and(item->item.eq("brand_id", brandId));
            }
        }
       if(StringUtils.isNotEmpty((String) params.get("status"))){
            Integer status = Integer.parseInt((String) params.get("status"));
            wrapper.and(item->item.eq("publish_status", status));
       }

        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

    @Transactional
    @Override
    public void saveSpuInfo(SpuSaveVo spuSaveVo) {
        //1、保存spu基本信息 pms_spu_info
        SpuInfoEntity spuInfo = new SpuInfoEntity();
        BeanUtils.copyProperties(spuSaveVo, spuInfo);
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date curDate = new Date();
        spuInfo.setCreateTime(curDate);
        spuInfo.setUpdateTime(curDate);

        spuInfoDao.insertSpuInfo(spuInfo);//这里插入数据后的返回值表示的是插入成功的数据
        Long spuId =  spuInfo.getId();//要这样取值，才能拿到返回的主键值！！

        //2、保存Spu的描述图片 pms_spu_info_desc
        SpuInfoDescEntity spuInfoDescEntity = new SpuInfoDescEntity();
        spuInfoDescEntity.setSpuId(spuId);
        spuInfoDescEntity.setDecript(gson.toJson(spuSaveVo.getDecript()));
        spuInfoDescDao.insert(spuInfoDescEntity);

        //3、保存spu的图片集 pms_spu_images
        SpuImagesEntity imagesEntity = new SpuImagesEntity();
        imagesEntity.setSpuId(spuId);
        imagesEntity.setImgUrl(gson.toJson(spuSaveVo.getImages()));
        spuImagesService.save(imagesEntity);


        //4、保存spu的规格参数;pms_product_attr_value
        List<BaseAttrs> baseAttrs = spuSaveVo.getBaseAttrs();
        List<ProductAttrValueEntity> productAttrValueEntities = new ArrayList<>();
        for (BaseAttrs baseAttr : baseAttrs) {
            ProductAttrValueEntity productAttrValueEntity = new ProductAttrValueEntity();
            productAttrValueEntity.setAttrId(baseAttr.getAttrId());
            productAttrValueEntity.setAttrValue(baseAttr.getAttrValues());
            productAttrValueEntity.setQuickShow(baseAttr.getShowDesc());
            productAttrValueEntity.setSpuId(spuId);
            AttrEntity attrEntity = attrDao.selectById(baseAttr.getAttrId());
            if(attrEntity != null){
                String attrName = attrEntity.getAttrName();
                productAttrValueEntity.setAttrName(attrName);
            }
            productAttrValueEntities.add(productAttrValueEntity);
        }
        productAttrValueDao.batchInsert(productAttrValueEntities);
        //5、保存spu的积分信息；gulimall_sms->sms_spu_bounds
        SpuBoundsDto spuBoundsDto = new SpuBoundsDto();
        spuBoundsDto.setSpuId(spuId);
        Bounds bounds = spuSaveVo.getBounds();
        if(bounds != null){
            spuBoundsDto.setGrowBounds(bounds.getGrowBounds());
            spuBoundsDto.setBuyBounds(bounds.getBuyBounds());
        }
        R r = couponFeignService.save(spuBoundsDto);
        if(r == null || r.getCode() != 0){
            log.error("保存spu积分信息异常");
        }
        //6、保存当前spu对应的所有sku信息；
        List<Skus> skuses = spuSaveVo.getSkus();
        List<SkuImagesEntity> skuImagesEntities = new ArrayList<>();
        if(skuses != null && skuses.size() > 0){
            skuses.forEach(item->{
                //6.1）、sku的基本信息；pms_sku_info
                SkuInfoEntity skuInfo = new SkuInfoEntity();
                skuInfo.setSkuName(item.getSkuName());
                skuInfo.setBrandId(spuSaveVo.getBrandId());
                skuInfo.setCatalogId(spuSaveVo.getCatalogId());
                skuInfo.setSkuTitle(item.getSkuTitle());
                skuInfo.setSkuSubtitle(item.getSkuSubtitle());
                skuInfo.setPrice(item.getPrice());
                skuInfo.setSkuDesc(gson.toJson(item.getDescar()));
                skuInfo.setSpuId(spuId);
                item.getImages().forEach(image->{
                    if(image.getDefaultImg() == 1){
                        skuInfo.setSkuDefaultImg(image.getImgUrl());
                    }
                });
                skuInfo.setSaleCount(0L);
                //6.2）、sku的图片信息；pms_sku_image
                SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
                item.getImages().forEach(img->{
                    if(img.getDefaultImg() == 1){
                        skuInfo.setSkuDefaultImg(img.getImgUrl());
                        skuImagesEntity.setDefaultImg(1);
                    }else{
                        skuImagesEntity.setDefaultImg(0);
                    }
                    skuImagesEntity.setImgUrl(img.getImgUrl());
                });
                // 通过这种方式插入数据库后，skuInfo的id会接收到自增的值
                skuInfoService.save(skuInfo);
                skuImagesEntity.setSkuId(skuInfo.getSkuId());
                skuImagesEntities.add(skuImagesEntity);
                //6.3）、sku的销售属性信息：pms_sku_sale_attr_value
                List<Attr> attrs = item.getAttr();
                List<SkuSaleAttrValueEntity> skuSaleAttrValueEntities = attrs.stream().map(attr -> {
                    SkuSaleAttrValueEntity skuSaleAttrValue = new SkuSaleAttrValueEntity();
                    skuSaleAttrValue.setSkuId(skuInfo.getSkuId());
                    skuSaleAttrValue.setAttrId(attr.getAttrId());
                    skuSaleAttrValue.setAttrName(attr.getAttrName());
                    skuSaleAttrValue.setAttrValue(attr.getAttrValue());
                    return skuSaleAttrValue;
                }).collect(Collectors.toList());
                skuSaleAttrValueService.saveBatch(skuSaleAttrValueEntities);
                //6.4）、sku的优惠、满减等信息；gulimall_sms
                // sms_sku_ladder
                // sms_sku_full_reduction
                // sms_member_price

                SkuReductionTo skuReductionTo = new SkuReductionTo();
                BeanUtils.copyProperties(item, skuReductionTo);
                skuReductionTo.setSkuId(skuInfo.getSkuId());
                couponFeignService.saveInfo(skuReductionTo);
            });
        }
//        skuInfoService.saveBatch(skuInfoEntities);
        skuImagesService.saveBatch(skuImagesEntities);


    }

    /**
     * 查到商品信息，封装成 List<SkuEsModel> skuEsModelList，并将信息保存到es
     * @param spuId
     */
    @Override
    public void spuUp(Long spuId) {
        List<SkuEsModel> skuEsModelList = new ArrayList<>();
        List<SkuInfoEntity> skus = skuInfoService.selectSkuInfoBySpuId(spuId);
        List<ProductAttrValueEntity> productAttrValueEntities = productAttrValueService.batchSelectProductAttrValue(spuId);
        List<Long> attrIds = productAttrValueEntities.stream().map(ProductAttrValueEntity::getAttrId).collect(Collectors.toList());

        //查询可被用作检索的属性
        List<Long> searchAttrIds = attrDao.selectSearchAttrs(attrIds);

        Set<Long> set = new HashSet<>(searchAttrIds);

        List<SkuEsModel.Attrs> searchAttrs = productAttrValueEntities.stream().filter(item->{
            return set.contains(item.getAttrId());
        }).map(item->{
            SkuEsModel.Attrs attr = new SkuEsModel.Attrs();
            BeanUtils.copyProperties(item, attr);
            return attr;
        }).collect(Collectors.toList());
        Map<Long, Integer> collect = null;
        try {
            List<SkuStockTo> data = wareFeignService.getSkuHasStock(skus.stream().map(item->item.getSkuId()).collect(Collectors.toList()));
            collect = data.stream().collect(Collectors.toMap(SkuStockTo::getSkuId, SkuStockTo::getStock));
        }catch (Exception e){
            log.error("获取商品库存时异常");
        }
        System.out.println("haha");
        for(SkuInfoEntity entity: skus){
            SkuEsModel skuEsModel = new SkuEsModel();
            BeanUtils.copyProperties(entity, skuEsModel);
            //skuPrice skuImg brandName brandImg catalogName attrs hasStock
            skuEsModel.setSkuPrice(entity.getPrice());
            skuEsModel.setSkuImg(entity.getSkuDefaultImg());
            if(collect == null){
                //如果feign因为网络波动等原因调用异常，默认设置商品 有库存
                skuEsModel.setHasStock(true);
            }else{
                skuEsModel.setHasStock(collect.get(entity.getSkuId()) > 0);
            }
            BrandEntity brand = brandService.getById(entity.getBrandId());
            skuEsModel.setBrandName(brand.getName());
            skuEsModel.setBrandImg(brand.getLogo());
            CategoryEntity category = categoryService.getById(entity.getCatalogId());
            skuEsModel.setCatalogName(category.getName());
            skuEsModel.setSkuImg(entity.getSkuDefaultImg());
            skuEsModel.setAttrs(searchAttrs);
            skuEsModelList.add(skuEsModel);
        }
        R search = searchFeignService.productStatusUp(skuEsModelList);
        if(search.getCode() == 0){
            this.updateStatus(spuId, Global.ProductConstant.SpuStatus.UP.getCode());
        }
//        System.out.println("haha");
    }

    @Override
    public void updateStatus(Long spuId, Long status) {
        spuInfoDao.updateStatus(spuId, status);
    }
}